package com.sari.common.persistence;

import com.sun.corba.se.impl.util.Utility;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementSetter;
import org.springframework.orm.hibernate4.HibernateCallback;
import org.springframework.orm.hibernate4.HibernateTemplate;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.*;

import static java.lang.Integer.parseInt;
import static org.springframework.orm.hibernate3.SessionFactoryUtils.getSession;

/**
 * DAO支持类实现
 *
 * @param <T>
 */
@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW )
public class BaseDao<T>{

    @Autowired
    private HibernateTemplate hibernateTemplate;

    @Autowired
    private JdbcTemplate jdbcTemplate;


    public BaseDao() {
    }

    public void batchUpdate(final String[] sql){
        this.jdbcTemplate.batchUpdate(sql);
    }

    protected int executeHql(final String var1) {
        Integer var3 = (Integer)this.hibernateTemplate.execute(new HibernateCallback() {
            public Object doInHibernate(Session var1x) throws HibernateException {
                Query var2 = var1x.createQuery(var1);
                int var3 = var2.executeUpdate();
                return new Integer(var3);
            }
        });
        return var3.intValue();
    }

    protected int executeHql(final String var1, final Object[] var2) {
        Integer var5 = (Integer)this.hibernateTemplate.execute(new HibernateCallback() {
            public Object doInHibernate(Session var1x) throws HibernateException {
                Query var2x = var1x.createQuery(var1);

                int var3;
                for(var3 = 0; var3 < var2.length; ++var3) {
                    var2x.setParameter(var3, var2[var3]);
                }

                var3 = var2x.executeUpdate();
                return new Integer(var3);
            }
        });
        return var5.intValue();
    }

    protected int executeHql(final String[] var1) {
        Integer var3 = (Integer)this.hibernateTemplate.execute(new HibernateCallback() {
            public Object doInHibernate(Session var1x) throws HibernateException {
                int var2 = 0;

                for(int var3 = 0; var3 < var1.length; ++var3) {
                    Query var4 = var1x.createQuery(var1[var3]);
                    var2 += var4.executeUpdate();
                }

                return new Integer(var2);
            }
        });
        return var3.intValue();
    }

    public Object uniqueResultHql(final String var1) {
        return this.hibernateTemplate.execute(new HibernateCallback() {
            public Object doInHibernate(Session var1x) throws HibernateException {
                Query var2 = var1x.createQuery(var1);
                var2.setMaxResults(1);
                return var2.uniqueResult();
            }
        });
    }

    public Object uniqueResultHql(final String var1, final Object... var2) {
        StringBuffer var3 = new StringBuffer(var1);
        var3.append(var2);
        final String var4 = var3.toString();
        return this.hibernateTemplate.execute(new HibernateCallback() {
            public Object doInHibernate(Session var1x) throws HibernateException {
                Query var2x = var1x.createQuery(var4);
                var2x.setMaxResults(1);
                return var2x.uniqueResult();
            }
        });
    }

    public Object loadObject(Class var1, Serializable var2) {
        return this.hibernateTemplate.get(var1, var2);
    }

    public Object loadObject(Class var1, String var2, Serializable var3) {
        StringBuffer var4 = new StringBuffer("from ");
        var4.append(var1.getName());
        var4.append(" where ");
        var4.append(var2);
        var4.append("=");
        var4.append(var3);
        final String var5 = var4.toString();
        return this.hibernateTemplate.execute(new HibernateCallback() {
            public Object doInHibernate(Session var1) throws HibernateException {
                Query var2 = var1.createQuery(var5);
                var2.setMaxResults(1);
                return var2.uniqueResult();
            }
        });
    }

    public Object loadObject(Class var1, String var2, String var3) {
        StringBuffer var4 = new StringBuffer("from ");
        var4.append(var1.getName());
        var4.append(" where ");
        var4.append(var2);
        var4.append("=\'");
        var4.append(var3);
        var4.append("\'");
        final String var5 = var4.toString();
        return this.hibernateTemplate.execute(new HibernateCallback() {
            public Object doInHibernate(Session var1) throws HibernateException {
                Query var2 = var1.createQuery(var5);
                var2.setMaxResults(1);
                return var2.uniqueResult();
            }
        });
    }

    public Object loadObject(String var1, String var2, String var3) {
        StringBuffer var4 = new StringBuffer("from ");
        var4.append(var1);
        var4.append(" where ");
        var4.append(var2);
        var4.append("=\'");
        var4.append(var3);
        var4.append("\'");
        final String var5 = var4.toString();
        return this.hibernateTemplate.execute(new HibernateCallback() {
            public Object doInHibernate(Session var1) throws HibernateException {
                Query var2 = var1.createQuery(var5);
                var2.setMaxResults(1);
                return var2.uniqueResult();
            }
        });
    }

    public void saveObject(T var1) {
        this.hibernateTemplate.save(var1);
    }

    public void saveObjects(final T[] var1) {
        this.hibernateTemplate.execute(new HibernateCallback() {
            public T doInHibernate(Session var1x) throws HibernateException {
                for(int var2 = 0; var2 < var1.length; ++var2) {
                    var1x.save(var1[var2]);
                    if(var2 % 20 == 0) {
                        var1x.flush();
                        var1x.clear();
                    }
                }

                return null;
            }
        });
    }

    public void saveObjects(final List var1) {
        this.hibernateTemplate.execute(new HibernateCallback() {
            public T doInHibernate(Session var1x) throws HibernateException {
                for(int var2 = 0; var2 < var1.size(); ++var2) {
                    var1x.save(var1.get(var2));
                    if(var2 % 20 == 0) {
                        var1x.flush();
                        var1x.clear();
                    }
                }

                return null;
            }
        });
    }

    public void updateObject(T var1) {
        this.hibernateTemplate.update(var1);
    }

    public void saveOrUpdate(T var1){
        this.hibernateTemplate.saveOrUpdate(var1);
    }


    public void updateObjects(final T[] var1) {
        this.hibernateTemplate.execute(new HibernateCallback() {
            public T doInHibernate(Session var1x) throws HibernateException {
                for(int var2 = 0; var2 < var1.length; ++var2) {
                    var1x.update(var1[var2]);
                    if(var2 % 20 == 0) {
                        var1x.flush();
                        var1x.clear();
                    }
                }

                return null;
            }
        });
    }

    public void updateObjects(final List var1) {
        this.hibernateTemplate.execute(new HibernateCallback() {
            public T doInHibernate(Session var1x) throws HibernateException {
                for(int var2 = 0; var2 < var1.size(); ++var2) {
                    var1x.update(var1.get(var2));
                    if(var2 % 20 == 0) {
                        var1x.flush();
                        var1x.clear();
                    }
                }

                return null;
            }
        });
    }

    public void updateObject(String var1, final T[] var2) {
        final String var3 = var1.toString();
        this.hibernateTemplate.execute(new HibernateCallback() {
            public T doInHibernate(Session var1) throws HibernateException {
                Query var2x = var1.createQuery(var3);

                for(int var3x = 0; var3x < var2.length; ++var3x) {
                    var2x.setParameter(var3x, var2[var3x]);
                }

                var2x.executeUpdate();
                return null;
            }
        });
    }


    public void deleteObject(Object var1) {
        this.hibernateTemplate.delete(var1);
    }

    public void deleteObject(Class var1, String var2, Serializable var3) {
        this.deleteObject((String)var1.getName(), var2, var3);
    }

    public void deleteObject(String var1, String var2, Serializable var3) {
        StringBuffer var4 = new StringBuffer("delete from ");
        var4.append(var1);
        var4.append(" where ");
        var4.append(var2);
        var4.append("=");
        var4.append(var3);
        this.hibernateTemplate.bulkUpdate(var4.toString());
    }

    public void deleteObjects(String var1, String var2, Serializable var3) {
        StringBuffer var4 = new StringBuffer("delete from ");
        var4.append(var1);
        var4.append(" where ");
        var4.append(var2);
        var4.append(" in (");
        var4.append(var3);
        var4.append(")");
        executeSql(var4.toString());
    }

    protected List listAll(String var1) {
        return this.hibernateTemplate.find(var1);
    }

    public List listAll(String var1, Object[] var2) {
        return this.hibernateTemplate.find(var1, var2);
    }
    //处理In的字符串数组加单引号问题
    protected List listAllIn(String var1,String var2){
        StringBuffer var3 = new StringBuffer();
        String[] tmp = var2.split(",");
        for(String varStr:tmp){
            var3.append(",'").append(varStr).append("'");
        }
        return this.hibernateTemplate.find(var1.replaceAll(":p1", var3.substring(1)));
    }

    public List listAll(Class var1) {
        return this.hibernateTemplate.loadAll(var1);
    }

    protected List listByHql(String var1, Object...values){
        return this.hibernateTemplate.find(var1, values);
    }

    protected List listByHql(final String var1, int var2, final int var3) {
        final int var4 = var3 * var2 - var3;
        return (List)this.hibernateTemplate.execute(new HibernateCallback() {
            public Object doInHibernate(Session var1x) throws HibernateException {
                Query var2 = var1x.createQuery(var1);
                var2.setFirstResult(var4);
                var2.setMaxResults(var3);
                return var2.list();
            }
        });
    }

    protected List listByHql(final String var1, final Object[] var2, int var3, final int var4) {
        final int var5 = var4 * var3 - var4;
        return (List)this.hibernateTemplate.execute(new HibernateCallback() {
            public Object doInHibernate(Session var1x) throws HibernateException {
                Query var2x = var1x.createQuery(var1);

                for (int var3 = 0; var3 < var2.length; ++var3) {
                    if (var2[var3] instanceof Date) {
                        var2x.setDate(var3, (Date) var2[var3]);
                    } else {
                        var2x.setParameter(var3, var2[var3]);
                    }
                }

                var2x.setFirstResult(var5);
                var2x.setMaxResults(var4);
                return var2x.list();
            }
        });
    }

    protected int listHqlCount(String var1) {
        int var2 = 0;
        List var3 = this.hibernateTemplate.find(var1);
        if(var3 != null && var3.size() > 0) {
            var2 = parseInt(var3.get(0).toString());
        }

        return var2;
    }

    protected int listHqlCount(String var1, Object[] var2) {
        int var3 = 0;
        List var4 = this.hibernateTemplate.find(var1, var2);
        if(var4 != null && var4.size() > 0) {
            var3 = parseInt(var4.get(0).toString());
        }

        return var3;
    }

    public String getStringParma(String var1, Object... var2){

        try {
            return getJdbcTemplate().queryForObject(var1,var2,String.class);
        }catch (EmptyResultDataAccessException e){
            return "";
        }
    }
    /**
     * @param sql
     * @param args
     * @param classT 注意该参数，jdbcTemplate.queryForObject传入的不能是自定义的classType，
     *               如果是自定义的，需要经过new BeanPropertyRowMapper<T>(classT)转换，默认支持的只有比如String，int等类型
     * @param <T>
     * @return
     */
    public <T> T findForObject(String sql, Class<T> classT, Object... args) {
        if (sql == null || sql.length() <= 0) {
            return null;
        }
        try {
            if (args == null || args.length <= 0) {
                return jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<T>(classT));
            }else {
                return jdbcTemplate.queryForObject(sql, args, new BeanPropertyRowMapper<T>(classT));
            }
        }catch (EmptyResultDataAccessException e){
            //  e.printStackTrace();
            return null;
        }
    }

    public <T> List<T> findList(String sql, Class<T> tClass, Object... params) {
        List<T> resultList = null;
        try {
            if (params != null && params.length > 0)
                resultList = jdbcTemplate.query(sql, params, new BeanPropertyRowMapper<T>(tClass));
            else
                // BeanPropertyRowMapper是自动映射实体类的
                resultList = jdbcTemplate.query(sql, new BeanPropertyRowMapper<T>(tClass));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return resultList;
    }

    public int saveOrUpdateOrDelete(String sql, final Object... params) {
        int num = 0;
        try {
            if (params == null || params.length == 0)
                num = jdbcTemplate.update(sql);
            else
                num = jdbcTemplate.update(sql, new PreparedStatementSetter() {
                    public void setValues(PreparedStatement ps) throws SQLException {
                        for (int i = 0; i < params.length; i++)
                            ps.setObject(i + 1, params[i]);
                    }
                });
        } catch (Exception e) {
            e.printStackTrace();
            num = -1;
        }
        return num;

    }

    protected void executeSql(String var1) {
        this.jdbcTemplate.execute(var1);
    }

    protected void executeSql(String var1, Object... var2) {
        this.jdbcTemplate.update(var1, var2);
    }

    protected List listBySql(String var1) {
        return this.jdbcTemplate.queryForList(var1);
    }

    public List listBySql(String var1, Object... var2) {
        try {
            return this.jdbcTemplate.queryForList(var1, var2);
        }catch (Exception e){
            //  e.printStackTrace();
            return null;
        }
    }

    public Map<String, Object> getObjectMap(String var1, Object... var2) {
        try {
            return this.jdbcTemplate.queryForMap(var1,var2);
        }catch (EmptyResultDataAccessException e){
            //  e.printStackTrace();
            return null;
        }
    }

    protected List listBySql(String var1,Object[] var2, int var3, int var4) {
        int var5 = var4 * var3 - var4;
        if(var5<0)
            var5 = 0;
        var1 += " limit "+var5+","+var4;
        return this.jdbcTemplate.queryForList(var1,var2);
    }

    protected int getCount(String var1,Object... var2) {
        try {
            return this.jdbcTemplate.queryForObject(var1,var2, Integer.class);
        }catch (NullPointerException e){
            //  e.printStackTrace();
            return 0;
        }
    }

    protected int listSqlCount(String var1, Object... var2) {
//        if(var1.indexOf("count")==-1&&var1.indexOf("COUNT")==-1){
//            var1 = "select count(*) from ("+var1+") tbcount";
//        }
        return this.jdbcTemplate.queryForObject(var1, var2, Integer.class);
    }

    public HibernateTemplate getHibernateTemplate() {
        return this.hibernateTemplate;
    }

    public JdbcTemplate getJdbcTemplate() {
        return this.jdbcTemplate;
    }

}